#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <math.h>

#include "matgl.h"
#include "camera.h"

#define PI 3.14159265359

CCamera::CCamera()
{
	angleH = 0.0f;
	angleV = 0.0f;
	CameraPosition[0] = 0.0f;
	CameraPosition[1] = 0.0f;
	CameraPosition[2] = -1.0f;
	CameraRotacao = MatrixRotationY(0.0f);
	Translation(0.0f, 0.0f, -1.0f);

	Projection(0.1f,100.0f,67.0f,4.0f/3.0f);
}

void CCamera::Rotation(float SetAngleH,float SetAngleV)
{
	CameraRotacao = MatrixMultiplication4x4(MatrixRotationX(SetAngleV), MatrixRotationY(SetAngleH));
	Mvisao = MatrixMultiplication4x4(CameraRotacao,CameraTranslacao);
}

void CCamera::SetRotation(float SetAngleH,float SetAngleV)
{
	angleH = SetAngleH;
	angleV = SetAngleV;
	Rotation(SetAngleH,SetAngleV);
}

void CCamera::TurnLeft(float AngleInc)
{
	angleH = angleH - AngleInc;
	Rotation(angleH,angleV);
}

void CCamera::TurnRight(float AngleInc)
{
	angleH = angleH + AngleInc;
	Rotation(angleH,angleV);
}

void CCamera::LookUp(float AngleInc)
{
	angleV = angleV - AngleInc;
	Rotation(angleH,angleV);
}

void CCamera::LookDown(float AngleInc)
{
	angleV = angleV + AngleInc;
	if (angleV > 90)
	{
		angleV = 90;
	} else if (angleV < -90)
	{
		angleV = -90;
	}

	Rotation(angleH,angleV);
}


void CCamera::MoveForward(float step)
{
	CameraPosition[0] += sin(angleH * PI/180.0f)*step;
	CameraPosition[2] += cos(angleH * PI/180.0f)*step;
	Translation(CameraPosition[0], CameraPosition[1], CameraPosition[2]);
}

void CCamera::MoveBackward(float step)
{
	CameraPosition[0] -= sin(angleH * PI/180.0f)*step;
	CameraPosition[2] -= cos(angleH * PI/180.0f)*step;
	Translation(CameraPosition[0], CameraPosition[1], CameraPosition[2]);
}

void CCamera::StrafeLeft(float step)
{
	CameraPosition[0] -= cos(angleH * PI/180.0f)*step;
	CameraPosition[2] += sin(angleH * PI/180.0f)*step;
	Translation(CameraPosition[0], CameraPosition[1], CameraPosition[2]);
}

void CCamera::StrafeRight(float step)
{
	CameraPosition[0] += cos(angleH * PI/180.0f)*step;
	CameraPosition[2] -= sin(angleH * PI/180.0f)*step;
	Translation(CameraPosition[0], CameraPosition[1], CameraPosition[2]);
}

void CCamera::MoveUp(float step)
{
	CameraPosition[1] += step;
	Translation(CameraPosition[0], CameraPosition[1], CameraPosition[2]);
}

void CCamera::MoveDown(float step)
{
	CameraPosition[1] -= step;
	Translation(CameraPosition[0], CameraPosition[1], CameraPosition[2]);
}


void CCamera::Translation(float x, float y, float z) 
{	
	CameraTranslacao = MatrixTranslation(-x, -y, z);
	Mvisao = MatrixMultiplication4x4(CameraRotacao,CameraTranslacao);
}


void CCamera::SetTranslation(float x, float y, float z) 
{	
	CameraPosition[0] = x;
	CameraPosition[1] = y;
	CameraPosition[2] = z;
	Translation( x, y, z);
}

void CCamera::Projection(float near, float far, float fov, float aspect) // clipping plane, clipping plane, convert 67 degrees to radians, aspect ratio
{
	fov = fov * PI/180.0f;
	Mprojecao = MatrixProjection(near,far,fov,aspect);
}

void CCamera::View(int visao_mat_location, int projecao_mat_location)
{
	//Mvisao = MatrixMultiplication4x4(CameraRotacao,CameraTranslacao);
	glUniformMatrix4fv(visao_mat_location, 1, GL_FALSE, Mvisao);
	glUniformMatrix4fv(projecao_mat_location, 1, GL_FALSE, Mprojecao);
}